package com.lyc.common.util;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.xml.soap.SAAJMetaFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

/**
 * @Author 李大神仙
 * @Date 2024/2/27 20:53
 * @Version 1.0
 */

@Component
public class RedisCaching {
    @Autowired
    @Qualifier("myRedisTemplate")
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 删除key
     * @param key
     */
    public void delete(String key){
        redisTemplate.delete(key);
    }

    /**
     * 批量删除key
     * @param keys
     */
    public void delete(Collection<String> keys){
        redisTemplate.delete(keys);
    }

    /**
     * 序列化key
     * @param key
     * @return
     */
    public byte[] dump(String key){
        return redisTemplate.dump(key);
    }

    /**
     * 是否存在key
     * @param key
     * @return
     */
    public Boolean exists(String key){
        return redisTemplate.hasKey(key);
    }

    /**
     * 设置过期时间
     * @param key
     * @param timeout
     * @param unit
     * @return
     */
    public Boolean expire(String key,long timeout, TimeUnit unit){
        return redisTemplate.expire(key,timeout,unit);
    }

    /**
     * 设置过期时间
     * @param key
     * @param date
     * @return
     */
    public Boolean expire(String key, Date date){
        return redisTemplate.expireAt(key,date);
    }

    /**
     * 查找匹配的key
     * @param pattern
     * @return
     */
    public Set<String> keys(String pattern){
        return redisTemplate.keys(pattern);
    }

    /**
     * 将当前数据库的key移动到给定的数据库db当中
     * @param key
     * @param dbIndex
     * @return
     */
    public Boolean move(String key,int dbIndex){
        return redisTemplate.move(key,dbIndex);
    }

    /**
     * 移除key的过期时间，key将持久保存
     * @param key
     * @return
     */
    public Boolean persist(String key){
        return redisTemplate.persist(key);
    }

    /**
     * 返回key的剩余过期时间
     * @param key
     * @param unit
     * @return
     */
    public Long getExpire(String key,TimeUnit unit){
        return redisTemplate.getExpire(key,unit);
    }

    /**
     * 返回key的剩余过期时间
     * @param key
     * @return
     */
    public Long getExpire(String key){
        return redisTemplate.getExpire(key);
    }

    /**
     * 从当前数据库中随机返回一个key
     * @return
     */
    public String randomKey(){
        return redisTemplate.randomKey();
    }

    /**
     * 修改key的名称
     * @param key
     * @param newKey
     */
    public void rename(String key,String newKey){
        redisTemplate.rename(key,newKey);
    }

    /**
     * 仅当newkey不存在时，将oldkey改名为newkey
     * @param oldKey
     * @param newKey
     * @return
     */
    public Boolean renameIfAbset(String oldKey,String newKey){
        return redisTemplate.renameIfAbsent(oldKey,newKey);
    }

    /**
     * 返回key所存储的值的类型
     * @param key
     * @return
     */
    public DataType type(String key){
        return redisTemplate.type(key);
    }

    /**
     * 设置设定key的值
     * @param key
     * @param value
     */
    public void set(String key,String value){
        redisTemplate.opsForValue().set(key,value);
    }

    /**
     * 获取指定key的值
     * @param key
     * @return
     */
    public Object get(String key){
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 返回key中字符串值的字符
     * @param key
     * @param stat
     * @param end
     * @return
     */
    public Object getRange(String key,long stat,long end){
        return redisTemplate.opsForValue().get(key,stat,end);
    }

    /**
     * 将给定key的值设为value，并返回key的旧值(old value)
     * @param key
     * @param value
     * @return
     */
    public Object getAndSet(String key,String value){
        return redisTemplate.opsForValue().getAndSet(key,value);
    }

    /**
     * 对key所存储的字符串值，获取指定偏移量上的位(bit)
     * @param key
     * @param offset
     * @return
     */
    public Boolean getBit(String key,long offset){
        return redisTemplate.opsForValue().getBit(key,offset);
    }

    /**
     * 批量获取
     * @param keys
     * @return
     */
    public List<Object> multiGet(Collection<String> keys){
        return redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 设置ASCII码，字符串'a'的ASCII码是97，转为二进制是'0110001',此方法是将二进制第offset位值变为value
     * @param key
     * @param offset
     * @param value
     * @return
     */
    public boolean setBit(String key,long offset,boolean value){
        return Boolean.TRUE.equals(redisTemplate.opsForValue().setBit(key,offset,value));
    }

    /**
     * 将值value关联到key,并将key的过期时间调为timeout
     * @param key
     * @param value
     * @param timeout
     * @param unit
     *  时间单位：天：TimeUnit.DAYS 小时：TimeUnit.HOURS 分种：TimeUnit.MINUTES
     *          秒：TimeUnit.SECONDS 毫秒：TimeUnit:MILLISECONDS
     */
    public void setEx(String key,String value,long timeout,TimeUnit unit){
        redisTemplate.opsForValue().set(key,value,timeout,unit);
    }

    /**
     * 只有在key不存在时设置key的值
     * @param key
     * @param value
     * @return
     */
    public boolean setIfAbsent(String key,String value){
        return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key,value));
    }

    /**
     * 用value参数覆写给定key所存储的字符串值，从偏移量offset开始
     * @param key
     * @param value
     * @param offset
     */
    public void setRange(String key,String value,long offset){
        redisTemplate.opsForValue().set(key,value,offset);
    }

    /**
     * 获取字符串长度
     * @param key
     * @return
     */
    public Long size(String key){
        return redisTemplate.opsForValue().size(key);
    }

    /**
     * 批量添加
     * @param maps
     */
    public void multiSet(Map<String,String> maps){
        redisTemplate.opsForValue().multiSet(maps);
    }

    /**
     * 同时设置一个或多个key-value对，当且仅当所有给定key都不存在时
     * @param maps
     * @return
     */
    public boolean multiSetIfAbsent(Map<String,String> maps){
        return Boolean.TRUE.equals(redisTemplate.opsForValue().multiSetIfAbsent(maps));
    }

    /**
     * 增加(自增长)，负数则为自减
     * @param key
     * @param increment
     * @return
     */
    public Long incrBy(String key,long increment){
        return redisTemplate.opsForValue().increment(key,increment);
    }

    public Double incrByFloat(String key,double increment){
        return redisTemplate.opsForValue().increment(key,increment);
    }

    /**
     * 追加到末尾
     * @param key
     * @param value
     * @return
     */
    public Integer append(String key,String value){
        return redisTemplate.opsForValue().append(key,value);
    }

    /**
     * 获取存储在哈希表中指定字段的值
     * @param key
     * @param field
     * @return
     */
    public Object hGet(String key,String field){
        return redisTemplate.opsForHash().get(key,field);
    }

    /**
     * 获取所有给定字段的值
     * @param key
     * @return
     */
    public Map<Object,Object> hGetAll(String key){
        return redisTemplate.opsForHash().entries(key);
    }

    public List<Object> hMultiGet(String key,Collection<Object> fields){
        return redisTemplate.opsForHash().multiGet(key,fields);
    }

    public void hPut(String key,String hashKey,String value){
        redisTemplate.opsForHash().put(key,hashKey,value);
    }

    public void hPutAll(String key,Map<String,String> maps){
        redisTemplate.opsForHash().putAll(key,maps);
    }

    /**
     * 仅当hashKey不存在时才设置
     * @param key
     * @param hasKey
     * @param value
     * @return
     */
    public Boolean hPutIfAbsent(String key,String hasKey,String value){
        return redisTemplate.opsForHash().putIfAbsent(key,hasKey,value);
    }

    /**
     * 删除一个或多个哈希表字段
     * @param key
     * @param fields
     * @return
     */
    public long hDelete(String key,Object... fields){
        return redisTemplate.opsForHash().delete(key,fields);
    }

    /**
     * 查看哈希表key中指定的字段是否存在
     * @param key
     * @param fields
     * @return
     */
    public boolean hExists(String key,String fields){
        return redisTemplate.opsForHash().hasKey(key,fields);
    }

    /**
     * 为哈希表key中的指定字段的整数值加上增量increment
     * @param key
     * @param field
     * @param increment
     * @return
     */
    public Long hIncrBy(String key,Object field,long increment){
        return redisTemplate.opsForHash().increment(key,field,increment);
    }

    public Double hIncrByFloat(String key,Object field,double delta){
        return redisTemplate.opsForHash().increment(key,field,delta);
    }

    /**
     * 获取所有哈希表中的字段
     * @param key
     * @return
     */
    public Set<Object> hKeys(String key){
        return redisTemplate.opsForHash().keys(key);
    }

    /**
     * 获取所有哈希表中的数量
     * @param key
     * @return
     */
    public Long hSize(String key){
        return redisTemplate.opsForHash().size(key);
    }

    /**
     * 获取所有哈希表中的所有值
     * @param key
     * @return
     */
    public List<Object> hValue(String key){
        return redisTemplate.opsForHash().values(key);
    }

    /**
     * 迭代哈希表中的键值对
     * @param key
     * @param scanOptions
     * @return
     */
    public Cursor<Map.Entry<Object,Object>> hScan(String key, ScanOptions scanOptions){
        return redisTemplate.opsForHash().scan(key,scanOptions);
    }

    /**
     * 通过索引获取列表的元素
     * @param key
     * @param index
     * @return
     */
    public Object lIndex(String key,long index){
        return redisTemplate.opsForList().index(key,index);
    }

    /**
     * 获取列表指定范围内的元素
     * @param key
     * @param start 开始位置，0开始
     * @param end   结束位置，-1返回所有
     * @param <T>
     * @return
     */
    public <T>List<T> lOtdRange(String key,long start,long end){
        List<List<T>> list = (List<List<T>>)lRange(key, start, end);
        return !CollectionUtils.isEmpty(list) ? list.get(0) : null;
    }

    public Object lRange(String k,long begin,long end){
        ListOperations<String, Object> stringObjectListOperations = redisTemplate.opsForList();
        return stringObjectListOperations.range(k,begin,end);
    }

    public Long lleftPushAll(String key,String...values){
        return redisTemplate.opsForList().leftPushAll(key,values);
    }

    public Long lleftPushALL(String key,Collection<String> vaue){
        return redisTemplate.opsForList().leftPushAll(key,vaue);
    }

    /**
     * 当list存在的时候才加入
     * @param key
     * @param value
     * @return
     */
    public Long lleftPushIfPresent(String key,String value){
        return redisTemplate.opsForList().leftPushIfPresent(key,value);
    }

    /**
     * 如果pivot存在，再pivot前面添加
     * @param key
     * @param pivot
     * @param value
     * @return
     */
    public Long lleftPush(String key,String pivot,String value){
        return redisTemplate.opsForList().leftPush(key,pivot,value);
    }

    public Long lRightPush(String key,String value){
        return redisTemplate.opsForList().rightPush(key,value);
    }

    public Long lRightPushAll(String key,Collection<String> value){
        return redisTemplate.opsForList().rightPushAll(key,value);
    }

    /**
     * 为已存在的列表添加值
     * @param key
     * @param value
     * @return
     */
    public Long lRightPushIfPresent(String key,String value){
        return redisTemplate.opsForList().rightPushIfPresent(key,value);
    }

    /**
     * 在pivot元素右边添加值
     * @param key
     * @param privot
     * @param value
     * @return
     */
    public Long lRightPush(String key,String privot,String value){
        return redisTemplate.opsForList().rightPush(key,privot,value);
    }

    /**
     * 通过索引设置列表元素的值
     * @param key
     * @param index
     * @param value
     */
    public void lSet(String key,long index,String value){
        redisTemplate.opsForList().set(key,index,value);
    }

    /**
     * 移出并获取列表的第一个元素
     * @param key
     * @return
     */
    public Object lleftPop(String key){
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 移出并获取列表的第一个元素，如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     * @param key
     * @param timeout
     * @param unit
     * @return
     */
    public Object lBleftPop(String key,long timeout,TimeUnit unit){
        return redisTemplate.opsForList().leftPop(key,timeout,unit);
    }

    /**
     * 移除并获取列表最后一个元素
     * @param key
     * @return
     */
    public Object lRleftPop(String key){
        return redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 移除并获取列表最后一个元素，如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     * @param key
     * @param timeout
     * @param unit
     * @return
     */
    public Object lBRleftPop(String key,long timeout,TimeUnit unit){
        return redisTemplate.opsForList().rightPop(key,timeout,unit);
    }

    /**
     * 移除并获取列表最后一个元素，并将元素添加到另一个列表并返回
     * @param key
     * @param destiationKey
     * @return
     */
    public Object lRleftPopAndLeftPush(String key,String destiationKey){
        return redisTemplate.opsForList().rightPopAndLeftPush(key,destiationKey);
    }

    /**
     * 从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它，如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     * @param sourceKey
     * @param destiationKey
     * @param timeout
     * @param unit
     * @return
     */
    public Object lBleftPopAndLeftPush(String sourceKey,String destiationKey,long timeout,TimeUnit unit){
        return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,destiationKey,timeout,unit);
    }

}

































